﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using Sissonix.Infrastructure.RepositoryFramework;
using Sissonix.Infrastructure.DomainBase;
using Sissonix.Infrastructure;
using System.Data;
using Sissonix.ExtRest.RestManagerModel.Model;

namespace Sissonix.ExtRest.RestManagerModel.Repository
{
    abstract class EFRepositoryBase<T> : RepositoryBase<T>, IUnitOfWorkRepository where T : IAggregateRoot
    {
        protected RestManagerEntities persistenceContext;
        protected string EFConnectionString;

        public EFRepositoryBase(UnitOfWork uow) : base(uow) { }
        public EFRepositoryBase() : base() { }

        public EFRepositoryBase(UnitOfWork uow, string ConnectionString) : base(uow) {
            EFConnectionString = ConnectionString;
        }
        public EFRepositoryBase(string ConnectionString) : base() {
            EFConnectionString = ConnectionString;
        }

        public override IUnitOfWork UnitOfWork
        {
            get { return unitOfWork; }
            set 
            {
                //TODO: Do we really care if the UOW HasRecords?  They might not even belong to
                //this repository.  A better check would be if this context has pending records
                //that need to go to the database.
                if (unitOfWork != null)
                {
                    if (this.unitOfWork.HasRecords) {
                        //TODO: Should this be a warning or error???
                    }
                }
                unitOfWork = value;

                InstantiateEFContext();
            }
        }

        protected RestManagerEntities GetEFContext()
        {
            if (persistenceContext != null)
                return persistenceContext;
            else
                return InstantiateEFContext();
        }

        private RestManagerEntities InstantiateEFContext()
        {
            if (EFConnectionString+"" != "")
                persistenceContext = new RestManagerEntities(EFConnectionString);
            else
                persistenceContext = new RestManagerEntities();

            return persistenceContext;
        }


        #region **====================** IUnitOfWorkRepository Members **====================**
        protected override void PersistNewItem(T item)
        {
            CheckContext();
            this.EFPersistNewItem(item);
        }

        protected override void PersistUpdatedItem(T item)
        {
            CheckContext();
            this.EFPersistUpdatedItem(item);
        }

        protected override void PersistDeletedItem(T item)
        {
            CheckContext();
            this.EFPersistDeletedItem(item);
        }

        public override void CommitPersistedItems()
        {
            //var x = persistenceContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged);
            //var y = persistenceContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
            //persistenceContext.AcceptAllChanges();
            persistenceContext.SaveChanges();
        }
        #endregion

        private void CheckContext()
        {
            if (persistenceContext == null)
                InstantiateEFContext();
        }

        #region **====================** IEFRepository  Members **====================**
        /*These methods are required in the inherited classes because they will be called
         * from the generic non-EF equivalent methods above */
        protected abstract void EFPersistNewItem(T item);
        protected abstract void EFPersistUpdatedItem(T item);
        protected abstract void EFPersistDeletedItem(T item);
        #endregion
    }
}
